﻿using System;
using System.ComponentModel;
using System.Linq;
using System.Net;
using System.ServiceModel.DomainServices.Client;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Arch.Samples.RiaServices.ServicesReferences;

namespace Arch.Samples.RiaServices.Services
{
    public partial class TodoContext
    {
        private bool registred;
        public bool IsBusy
        {
            get
            {
                if (!registred)
                {
                    PropertyChanged += TodoContextPropertyChanged;
                    registred = true;
                }
                return IsLoading || IsSubmitting;
            }
        }

        void TodoContextPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "IsSubmitting" || e.PropertyName == "IsLoading")
                RaisePropertyChanged("IsBusy");
        }


        public LoadOperation Load<TEntity>(EntityQuery<TEntity> query, Action<LoadOperation<TEntity>> callback, LoadBehavior loadBehavior = LoadBehavior.KeepCurrent)
            where TEntity : Entity
        {
            return Load(query, loadBehavior, callback, null);
        }

        public override LoadOperation Load(EntityQuery query, LoadBehavior loadBehavior, Action<LoadOperation> callback, object userState)
        {
            return base.Load(query, loadBehavior, op => ManageLoadCallBack(op, query, loadBehavior, callback, userState), userState);
        }

        private void ManageLoadCallBack(LoadOperation operation, EntityQuery query, LoadBehavior loadBehavior, Action<LoadOperation> callback, object userState)
        {
            var options = (userState as ServiceOptions) ?? ServiceOptions.Default;

            if (options.ManageError && operation.HasError)
            {
                string message;

                if (operation.ValidationErrors.Count() > 0)
                {
                    message = string.Join(", ", operation.ValidationErrors);
                }
                else
                {
                    message = operation.Error.ToString();
                }

                MessageBox.Show(message);
                operation.MarkErrorAsHandled();

                if (!options.ExecuteOnError) return;
            }

            if(callback != null)
                callback(operation);
        }

        public override SubmitOperation SubmitChanges(Action<SubmitOperation> callback, object userState)
        {
            return base.SubmitChanges(op => ManageSubmitCallBack(op, callback, userState), userState);
        }

        private void ManageSubmitCallBack(SubmitOperation operation, Action<SubmitOperation> callback, object userState)
        {
            var options = (userState as ServiceOptions) ?? ServiceOptions.Full;

            if (options.ManageError && operation.HasError)
            {
                string message;

                if (operation.EntitiesInError.Count() > 0)
                {
                    StringBuilder builder = new StringBuilder();
                    builder.AppendLine("Error on entities");
                    foreach (var entity in operation.EntitiesInError)
                    {
                        builder.AppendLine(string.Format("{0} : {1}", entity, string.Join(", ", entity.ValidationErrors)));
                    }
                    message = builder.ToString();
                }
                else
                {
                    message = operation.Error.ToString();
                }

                MessageBox.Show(message);
                operation.MarkErrorAsHandled();

                if (!options.ExecuteOnError) return;
            }
            callback(operation);
        }
    }
}
